package com.sunop.comment.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunop.api.client.user.UserClient;
import com.sunop.api.model.UserBaseDTO;
import com.sunop.comment.mapper.CommentMapper;
import com.sunop.comment.model.*;
import com.sunop.comment.service.CommentService;
import com.sunop.panticommon.entity.PageResult;
import com.sunop.panticommon.entity.Result;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.Set;


/**
 * @since 2025-03-22
 */
@Service
@AllArgsConstructor
@Slf4j
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    private final UserClient userClient;
    private final CommentMapper commentMapper;
    private final RedisTemplate redisTemplate;


    @Override
    public Result sendComment(CommentSendDTO commentSendDTO) {
        Comment comment = new Comment();
        BeanUtil.copyProperties(commentSendDTO, comment);
        if(!StpUtil.isLogin())throw new RuntimeException("请先登录");
        int uid = StpUtil.getLoginIdAsInt();
        try {
            UserBaseDTO userBaseDTO = userClient.getUserBaseDTO(uid);
            BeanUtil.copyProperties(userBaseDTO, comment);
            commentMapper.insert(comment);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return Result.success(null, "评论成功");

    }

    @Override
    public PageResult pageQuery(CommentPageQueryDTO commentPageQueryDTO) {
        parameterCheck(commentPageQueryDTO);
        PageHelper.startPage(commentPageQueryDTO.getPageNum(), commentPageQueryDTO.getPageSize());
        Page<Comment> page = commentMapper.pageQuery(commentPageQueryDTO);
        return new PageResult(page.getTotal(), page.getResult());
    }

    @Override
    public Result delById(Integer id) {
        if (commentMapper.selectCidById(id) != StpUtil.getLoginIdAsInt())
            return Result.error("删除失败，您不是该评论的作者");
        commentMapper.deleteById(id);
        return Result.success(null, "删除成功");
    }

    @Override
    public Result sendReply(CommentReplyDTO commentSendDTO) {
        CommentReplyPO commentReplyPO = new CommentReplyPO();
        BeanUtil.copyProperties(commentSendDTO, commentReplyPO);
        int uid = StpUtil.getLoginIdAsInt();
        try {
            UserBaseDTO userBaseDTO = userClient.getUserBaseDTO(uid);
            BeanUtil.copyProperties(userBaseDTO, commentReplyPO);
            commentMapper.insertReply(commentReplyPO);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return Result.success(null, "回复成功");
    }

    @Override
    public PageResult replyPageQuery(CommentPageQueryDTO commentPageQueryDTO, int cid) {
        parameterCheck(commentPageQueryDTO);
        PageHelper.startPage(commentPageQueryDTO.getPageNum(), commentPageQueryDTO.getPageSize());
        Page<CommentReplyPO> page = commentMapper.replyPageQuery(cid, commentPageQueryDTO);
        return new PageResult(page.getTotal(), page.getResult());
    }

    @Override
    public Result delReplyById(Integer id) {
        if (commentMapper.selectReplyCidById(id) != StpUtil.getLoginIdAsInt())
            return Result.error("删除失败，您不是该评论的作者");
        commentMapper.deleteReplyById(id);
        return Result.success(null, "删除成功");
    }

    @Override
    public Result commentLike(Integer commentId) {
        try {
            redisTemplate.opsForSet().add("like:" + "comment:" + commentId + ":user:" + StpUtil.getLoginIdAsInt(), commentId);
            redisTemplate.opsForValue().increment("like:" + "comment:" + commentId);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return Result.success(null, "点赞成功");
    }

    @Override
    public Result commentUnlike(Integer commentId) {
        try {
            redisTemplate.opsForSet().remove("like:" + "comment:" + commentId + ":user:" + StpUtil.getLoginIdAsInt(), commentId);
            redisTemplate.opsForValue().decrement("like:" + "comment:" + commentId);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return Result.success(null, "取消点赞成功");
    }

    @Override
    public Result collectComment(Integer commentId) {
        try {
            // 获取当前用户 ID
            int userId = StpUtil.getLoginIdAsInt();
            // 将讨论帖 ID 添加到用户的有序集合中，Score 为当前时间戳
            double score = System.currentTimeMillis();
            redisTemplate.opsForZSet().add("user:comment:collect:" + userId, commentId, score);
            return Result.success(null, "收藏成功");
        } catch (Exception e) {
            throw new RuntimeException("收藏失败", e);
        }
    }

    @Override
    public Result uncollectComment(Integer commentId) {
        try {
            // 获取当前用户 ID
            int userId = StpUtil.getLoginIdAsInt();
            // 将讨论帖 ID 从用户的有序集合中移除
            redisTemplate.opsForZSet().remove("user:comment:collect:" + userId, commentId);
            return Result.success(null, "取消收藏成功");
        } catch (Exception e) {
            throw new RuntimeException("取消收藏失败", e);
        }
    }

    // 获取收藏的讨论帖列表
    @Override
    public Result getCollectedComments(int page, int size, boolean reverseOrder) {
        try {
            // 获取当前用户 ID
            int userId = StpUtil.getLoginIdAsInt();
            // 计算分页的起始和结束位置
            long start = (page - 1) * size;
            long end = start + size - 1;
            // 根据排序规则获取分页数据
            Set<Integer> commentIds;
            if (reverseOrder) {
                // 倒序：按 Score 从大到小排序
                commentIds = redisTemplate.opsForZSet().reverseRange("user:comment:collect:" + userId, start, end);
            } else {
                // 正序：按 Score 从小到大排序
                commentIds = redisTemplate.opsForZSet().range("user:comment:collect:" + userId, start, end);
            }
            // 返回收藏的讨论帖 ID 列表
            return Result.success(commentIds, "获取收藏列表成功");
        } catch (Exception e) {
            throw new RuntimeException("获取收藏列表失败", e);
        }
    }

    @Override
    public long getCollectedCount() {
        try {
            // 获取当前用户 ID
            int userId = StpUtil.getLoginIdAsInt();
            // 获取用户的有序集合大小
            return redisTemplate.opsForZSet().size("user:comment:collect:" + userId);
        } catch (Exception e) {
            throw new RuntimeException("获取收藏总数失败", e);
        }
    }

    @Override
    public boolean isCommentCollected(Integer commentId) {
        try {
            // 获取当前用户 ID
            int userId = StpUtil.getLoginIdAsInt();
            // 检查讨论帖 ID 是否在用户的有序集合中
            return redisTemplate.opsForZSet().score("user:comment:collect:" + userId, commentId) != null;
        } catch (Exception e) {
            throw new RuntimeException("检查收藏状态失败", e);
        }
    }

    private static void parameterCheck(CommentPageQueryDTO commentPageQueryDTO) {
        if (commentPageQueryDTO.getPageNum() < 1 || commentPageQueryDTO.getPageSize() < 1) {
            throw new IllegalArgumentException("Invalid pageNum or pageSize value");
        }
        List<String> allowedSortBy = Arrays.asList("id", "comment_num", "submit_num", "pass_num", "create_time");
        List<String> allowedOrderBy = Arrays.asList("asc", "desc");
        if (!allowedSortBy.contains(commentPageQueryDTO.getSortBy())) {
            throw new IllegalArgumentException("Invalid sortBy value: " + commentPageQueryDTO.getSortBy());
        }
        if (!allowedOrderBy.contains(commentPageQueryDTO.getOrderBy())) {
            throw new IllegalArgumentException("Invalid orderBy value: " + commentPageQueryDTO.getOrderBy());
        }
    }
}
